#include "catalog.h"
#include "query.h"
#include "index.h"

// A simple scan select using a heap file scan
Status Operators::ScanSelect(const string & result,      // name of the output relation
	                     const int projCnt,          // number of attributes in the projection
                             const AttrDesc projNames[], // The projection list (as AttrDesc)
                             const AttrDesc *attrDesc,   // the attribute in the selection predicate
                             const Operator op,          // the predicate operation
                             const void *attrValue,      // a pointer to the literal value in the predicate
                             const int reclen)           // length of a tuple in the result relation
{
  cout << "Algorithm: File Scan" << endl;
  Status heapfilescanstatus;
  Status nextstatus;
  Status endscanstatus;
  Record nextrec;
  RID nextrid;
  HeapFileScan resultheapfile(result, nextstatus);

  Record result_rec;
  result_rec.length = reclen;
  result_rec.data = malloc(reclen);
  RID result_RID;

  if(nextstatus != OK)
	  return nextstatus;

  if(attrValue == NULL)
  {
	  HeapFileScan heapfilescan(projNames[0].relName, heapfilescanstatus);

	  if(heapfilescanstatus != OK)
		  return heapfilescanstatus;

	  heapfilescan.startScan(0, 0, (Datatype)NULL,
			  NULL, (Operator)NULL);

	  while(nextstatus != NOMORERECS)
	  {
		  nextstatus = heapfilescan.scanNext(nextrid, nextrec);
		  if(nextstatus == OK)
		  {
			  resultheapfile.insertRecord(nextrec, nextrid);
			  //put into result heapfile
		  }
		  if(nextstatus == FILEEOF)
			  break;
		  if((nextstatus != OK) && (nextstatus != NOMORERECS))
		  {
			  return nextstatus;
		  }
	  }
	  endscanstatus = heapfilescan.endScan();

	  if(endscanstatus != OK)
		  return endscanstatus;
  }
  else
  {
	  HeapFileScan heapfilescan(attrDesc->relName, attrDesc->attrOffset, 
		 	 attrDesc->attrLen, (Datatype)attrDesc->attrType,
		  	(const char*)attrValue, op, heapfilescanstatus);

	  if(heapfilescanstatus != OK)
	  	return heapfilescanstatus;

	  while(nextstatus != NOMORERECS)
	  {
		  nextstatus = heapfilescan.scanNext(nextrid, nextrec);
		  if(nextstatus == OK)
		  {
            int result_offset = 0;
		    //loop through to fill in data
		    for(int i = 0; i < projCnt; i++)
		    {
	    	    if(projNames[i].attrLen + result_offset > result_rec.length)
	    		{
	    			return ATTRTOOLONG;
	    		}
	    		memcpy((char*)result_rec.data + result_offset, 		
	    			(char*)nextrec.data + projNames[i].attrOffset, projNames[i].attrLen);
	    				
	    		result_offset += projNames[i].attrLen;
	    			
	    	}
            //put the result rec in the heapfile
			  Status insert_status = resultheapfile.insertRecord(result_rec, result_RID);
              if(insert_status != OK)
                   return insert_status;
		  }
		  if(nextstatus == FILEEOF)
			  break;
		  if((nextstatus != OK) && (nextstatus != NOMORERECS))
		  {
			  return nextstatus;
		  }
	  }
	  endscanstatus = heapfilescan.endScan();

	  if(endscanstatus != OK)
		  return endscanstatus;
  }
  free(result_rec.data);
  return OK;
}
